﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace CookingTrans
{
    class Rapi
    {
        //api初始化，会一直等待设备连接
        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        internal static extern int CeRapiInit();
        //扩展的初始化，只检查一次设备是否连接
        [DllImport("rapi.dll")]
        public static extern void CeRapiInitEx(ref RapiInitRes pRapiInit);
        //获取初始化时的错误码
        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        internal static extern int CeRapiGetError();
        //关闭初始化
        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        internal static extern int CeRapiUninit();

        [DllImport("rapi.dll", CharSet=CharSet.Unicode)] 
        internal static extern int CeCloseHandle(IntPtr hObject); 
        [DllImport("rapi.dll", CharSet=CharSet.Unicode)] 
        internal static extern int CeWriteFile(IntPtr hFile, byte[] lpBuffer, int nNumberOfbytesToWrite, ref int lpNumberOfbytesWritten, int lpOverlapped); 
        [DllImport("rapi.dll", CharSet=CharSet.Unicode, SetLastError=true)] 
        internal static extern IntPtr CeCreateFile( string lpFileName, uint dwDesiredAccess, int dwShareMode, int lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, int hTemplateFile);
        //删除文件
        [DllImport("rapi.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        internal static extern bool CeDeleteFile(string lpFileName);
        
        //自定义返回类型结构
        [StructLayout(LayoutKind.Sequential)]
        public struct RapiInitRes
        {
            public int cbsize;
            public IntPtr heRapiInit;
            public UInt32 hrRapiInit;
        }
        /// <summary>
        /// 扩展的初始化RAPI，只检查一次设备是否连接
        /// </summary>
        /// <returns></returns>
        public static bool RapiInitEx()
        {
            try
            {
                //函数使用
                var r = new RapiInitRes();
                r.cbsize = Marshal.SizeOf(r);
                CeRapiInitEx(ref r);
                if (r.hrRapiInit != 0)
                {
                    // 连接失败，显示失败代码 
                    Console.WriteLine("Error while Connecting,errorcode:{0}", r.hrRapiInit);
                    return false;
                }
            }
            catch(Exception e)
            {
                Console.WriteLine(e.ToString());
                return false;
            }
            return true;
        }

        /// <summary>
        /// 初始化RAPI，会一直等待设备连接
        /// </summary>
        /// <returns></returns>
        public static bool RapiInit()
        {
            try
            {
                if (CeRapiInit() != 0)
                {
                    // 连接失败，显示失败代码 
                    Console.WriteLine("Error while Connecting,errorcode:{0}", CeRapiGetError());
                    return false;
                }
            }
            catch(Exception e)
            {
                Console.WriteLine(e.ToString());
                return false;
            }
            return true;
        }

        /// <summary>
        /// 关闭初始化RAPI
        /// </summary>
        public static void RapiUnInit()
        {
            CeRapiUninit();
        }

        private const uint GenericWrite = 0x40000000; // 设置读写权限 
        private const short CreateNew = 1; // 创建新文件 
        private const short FileAttributeNormal = 0x80; // 设置文件属性 
        private const short InvalidHandleValue = -1; // 错误句柄 
        /// <summary>
        /// 往设备中复制文件
        /// </summary>
        /// <param name="localFileName">本地文件</param>
        /// <param name="remoteFileName">目标文件</param>
        public static bool CopyToRemoteFile(string localFileName, string remoteFileName)
        {
            CeDeleteFile(remoteFileName + Path.GetFileName(localFileName));
            // 创建远程文件 
            var remoteFile = CeCreateFile(remoteFileName + Path.GetFileName(localFileName), GenericWrite, 0, 0,
                                          CreateNew, FileAttributeNormal, 0);
            // 检查文件是否创建成功 
            if ((int)remoteFile == InvalidHandleValue)
            {
                Console.WriteLine("Could not create remote file");
                return false;
            } 
            // 打开本地文件 
            var localFile = new FileStream(localFileName, FileMode.Open);
            // 读取1K字节 
            int filePos = 0;
            var buffer = new byte[0x400]; // 传输缓冲区定义为1k 
            int bytesread = localFile.Read(buffer, filePos, buffer.Length);
            while(bytesread > 0)
            {
                // 移动文件指针到已读取的位置 
                filePos += bytesread;
                // 写缓冲区数据到远程设备文件 
                int byteswritten = 0;
                if(! Convert.ToBoolean(CeWriteFile(remoteFile, buffer, bytesread, ref byteswritten, 0))) 
                {
                    //不成功关闭文件句柄，抛出异常 
                    CeCloseHandle(remoteFile);
                    Console.WriteLine("Could not write to remote file");
                    return false;
                } 
                try 
                {
                    // 重新填充本地缓冲区 
                    bytesread = localFile.Read(buffer, 0, buffer.Length);
                } 
                catch(Exception) 
                { 
                    bytesread = 0;
                } 
            }
            // 关闭本地文件 
            localFile.Close();
            // 关闭远程文件 
            CeCloseHandle(remoteFile);
            return true;
        }
    }
}
